package com.atguigu.srb.oss.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.atguigu.srb.oss.service.FileService;
import com.atguigu.srb.oss.util.OssProperties;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.UUID;

@Slf4j
@Service
public class FileServiceImpl implements FileService {

    /**
     * 文件上传至阿里云OSS
     *
     * @param inputStream 文件输入流
     * @param module      业务模块名，用于文件分类
     * @param fileName    原始文件名
     * @return 文件在OSS上的完整访问URL
     */
    @Override
    public String upload(InputStream inputStream, String module, String fileName) {
        log.info("开始上传文件至OSS，模块: {}, 原始文件名: {}", module, fileName);

        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(OssProperties.ENDPOINT, OssProperties.KEY_ID, OssProperties.KEY_SECRET);

        try {
            // 检查存储桶是否存在，不存在则创建并设置公共读权限
            if (!ossClient.doesBucketExist(OssProperties.BUCKET_NAME)) {
                log.info("创建OSS存储桶: {}", OssProperties.BUCKET_NAME);
                ossClient.createBucket(OssProperties.BUCKET_NAME);
                ossClient.setBucketAcl(OssProperties.BUCKET_NAME, CannedAccessControlList.PublicRead);
                log.info("存储桶 {} 创建成功并设置为公共读", OssProperties.BUCKET_NAME);
            }

            // 构建日期路径结构（年/月/日）
            String folder = new DateTime().toString("yyyy/MM/dd");

            // 生成唯一文件名（UUID+原文件扩展名）
            String fileExtension = fileName.substring(fileName.lastIndexOf("."));
            String uniqueFileName = UUID.randomUUID().toString() + fileExtension;
            log.debug("生成唯一文件名: {}", uniqueFileName);

            // 构建完整的OSS对象键（包含模块名、日期路径和文件名）
            String objectKey = module + "/" + folder + "/" + uniqueFileName;
            log.debug("文件将存储在OSS路径: {}", objectKey);

            // 执行文件上传
            ossClient.putObject(OssProperties.BUCKET_NAME, objectKey, inputStream);
            log.info("文件上传成功，OSS对象键: {}", objectKey);

            // 构建并返回完整的访问URL
            String fileUrl = "https://" + OssProperties.BUCKET_NAME + "." + OssProperties.ENDPOINT + "/" + objectKey;
            log.info("文件访问URL: {}", fileUrl);

            return fileUrl;
        } catch (Exception e) {
            log.error("文件上传失败，模块: {}, 原始文件名: {}", module, fileName, e);
            throw e;
        } finally {
            // 确保关闭OSS客户端连接
            if (ossClient != null) {
                ossClient.shutdown();
                log.debug("OSS客户端已关闭");
            }
        }
    }

    /**
     * 根据URL删除OSS上的文件
     *
     * @param url 文件在OSS上的完整访问URL
     */
    @Override
    public void removeFile(String url) {
        log.info("开始删除OSS文件，URL: {}", url);

        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(OssProperties.ENDPOINT, OssProperties.KEY_ID, OssProperties.KEY_SECRET);

        try {
            // 从URL中提取对象键
            String host = "https://" + OssProperties.BUCKET_NAME + "." + OssProperties.ENDPOINT + "/";
            String objectKey = url.substring(host.length());
            log.debug("从URL提取的OSS对象键: {}", objectKey);

            // 执行文件删除
            ossClient.deleteObject(OssProperties.BUCKET_NAME, objectKey);
            log.info("文件删除成功，OSS对象键: {}", objectKey);
        } catch (Exception e) {
            log.error("文件删除失败，URL: {}", url, e);
            throw e;
        } finally {
            // 确保关闭OSS客户端连接
            if (ossClient != null) {
                ossClient.shutdown();
                log.debug("OSS客户端已关闭");
            }
        }
    }
}